/* api */
import { dialout, getTaskAllotList, getTaskTypesMap } from '@src/api/TaskApi'
import { ctiCallOut } from '@src/util/ctisdk'
/* computed */
import AllotMapDialogComputed from '@src/modules/task/taskTypes/allot/components/AllotMapDialog/AllotMapDialogComputed'
/* component */
/* enum */
import EventNameEnum from '@model/enum/EventNameEnum'
import TableNameEnum from '@model/enum/TableNameEnum'
/* entity */
import EsTask from '@model/entity/EsTask'
import TaskType from '@model/entity/TaskType'
import Field from '@model/entity/Field'
import TaskTypeSimple from '@model/entity/TaskTypeSimple'
/* model */
import { BEIJING_LATITUDE, BEIJING_LONGITUDE } from '@src/model/const/Number'
import { getTaskTypesResult } from '@model/param/out/Task'
import { AllotMapDialogMarker } from '@src/modules/task/taskTypes/allot/components/AllotMapDialog/AllotMapDialogModel'
import { ALLOT_TASK_REQUIRED_MASSAGE } from '@src/model/const/Alert'
/* service */
import { getTaskId, getTemplateId } from '@service/TaskService'
import { isPlanTimeField } from '@service/FieldService'
/* util */
import Log from '@src/util/log'
import Platform from '@src/util/platform'
import { isArray, isEmpty, isObject, isUndefined } from '@src/util/type'
import { debounce } from '@src/util/function'
import { isCalendar } from '@src/util/CalendarUtil';
import i18n from '@src/locales'


import { useNewVue } from '@hooks/useNewVue'
const { extendVue } = useNewVue();

class AllotMapDialogMethods extends AllotMapDialogComputed {
  
  public buildTaskMapMarkerContent(task: EsTask, index: number): string {
    return `<div id="map-mark${index}" class="just-cur-point map-mark ${task.selected ? 'selected' : ''}">${index + 1}</div>`
  }
  
  /**
   * @description 关闭地图标记弹窗
   */
  public closeInfoWindowHandler() {}

  // 点击右侧普通面板条目
  public clickListItem(task: EsTask, index: number): void {
    this.openInfo({markKey:task.id, editInfo:true}, false)
  }

  // 选择右侧check按钮
  public checkListItem(task: EsTask, index: number): void {
    const selected = task.selected || false
    this.changeListItem(selected, task, index)
  }

  // 更新列表数据
  public changeListItem(selected: boolean | undefined, task: EsTask, index: number): void {
    // 更改选中状态
    this.toggleMapTaskSelected(index, selected)
  }
  
  public chooseSideListTaskClickHandler(task: EsTask, index: number): void {
    
  }

  public infoWindowFnc({mapIndex, markKey}){
    this.openInfo({markKey, editInfo:false}, false)
  }

  public changeInfoWindowContent(markKey){
    let div = document.createElement("div")
    div.className = 'bg-w task-map-info-window'
    div.append(this.$refs.TaskMapInfoWindowComponent.$el)
    this.$refs.baseMapContainer.changeInfoWindow({markKey, content:div})
  }

  public openInfo({markKey, editInfo}, scroll? = true){
    const key_ = markKey
    const oldIndex = this.taskMapData.findIndex(i=>i.isClick);
    let oldItem;
    if(oldIndex > -1){
      // 先关闭
      oldItem = this.taskMapData[oldIndex];
      this.$set(this.taskMapData[oldIndex], 'isClick', false)
      if(editInfo){
        this.$refs.baseMapContainer.openInfoWindow({ markKey:oldItem.id })
      }
    }
    if(key_ && oldItem?.id !== key_){
      const index = this.taskMapData.findIndex(i=>i.id == key_)
      const item = this.taskMapData[index]
      //选中
      this.$set(this, 'currentSelectedMarkTask', {data:item, index})
      this.$set(this.taskMapData[index], 'isClick', true)
      if(editInfo){
        this.visibleMapInfoWindow = true
        this.$nextTick(()=>{
          this.$refs.baseMapContainer.openInfoWindow({ markKey:item.id })
          this.changeInfoWindowContent(item.id)
        })
        this.setCurrentSelectedMarkTaskPlantimeField(item)
        if(scroll){
          this.scrollSideToSelectedTask({data:item,index})
        }
        
      }
    }
    
  }

  

  public createMarker(item: EsTask, index: number): AMap.Marker | null {
      let taskAddress = item?.address || {}
    
      if(!taskAddress.longitude || !taskAddress.latitude) return null

      const markCon = this.buildTaskMapMarkerContent(item, index)
      const div = document.createElement("div")
      div.innerHTML = 'test'
      return {
        lat:taskAddress.latitude,
        lng:taskAddress.longitude,
        size:{
          x:32,
          y:32
        },
        markInfo:markCon,
        infoWindow:div,
        markClickFn:(event:any, item:any) => {
          const { markKey } = item;
          this.openInfo({markKey, editInfo:true})
        },
        markKey:item.id
      };
  }


  
  
  
  public debouncedLoadmoreAllotList() {
    debounce(() => {
      this.loadmoreAllotList()
    })
  }
  
  /** 
   * @description 获取工单类型 
  */
  public fetchTaskTypesMap() {
    if (!isEmpty(this.taskTypes)) return
    
    this.loading = true
    return (
      getTaskTypesMap().then((data: getTaskTypesResult) => {
        const isSuccess = data.success
        if (!isSuccess) return
        
        const taskTypeSimpleList: TaskTypeSimple[] = data?.result || []
        this.taskTypes = taskTypeSimpleList.map(taskTypeSimple => TaskTypeSimple.toTaskType(taskTypeSimple))
        // key : 工单类型id(string) -> value: TaskType
        this.taskTypesMap = (
          this.taskTypes
            .reduce((acc: Record<string, TaskType>, currentTaskType: TaskType) => {
              acc[currentTaskType.templateId] = currentTaskType
              return acc
            }, {})
        )
      }).catch(err => {
        console.error(err)
      })
    )
  }
  
  async fetchAllotList() {
    this.loading = true
    this.searchParams.page++

    let params = {
      ...this.advancedSearchParams,
      ...this.searchParams,
      ids: this.taskIdList,
      pageSize: 50,
      inApprove: 0
    }

    try {
      let data = await getTaskAllotList(params)
      let allotTaskList = data?.result?.content || []
      this.hasNextPage = this.searchParams.page < Number(data?.result?.totalPages || 0)
      
      return allotTaskList
      // return allotTaskList.filter((task: EsTask) => task?.address?.latitude && task?.address?.longitude)
      
    } catch (error) {
      Log.error(error, this.fetchAllotList.name)
      return []
    } finally {
      this.loading = false
    }
  }
  
  public getTaskType(task?: EsTask): TaskType | undefined {
    const templateId: string = getTemplateId(task)
    return this.taskTypesMap[templateId]
  }
  
  public getAllotMapDialogAttributes(): Record<string, any> {
    return {
      directives: [
        {
          name: 'loading',
          value: this.loading
        }
      ]
    }
  }
  
  public async initializeAllotList(): Promise<void> {
    this.searchParams.page = 0
    this.taskMapData = await this.fetchAllotList()
    
    this.renderMap(this.taskMapData)
  }
  
  public async loadmoreAllotList(): Promise<void> {
    const nowLength = this.taskMapData.length
    const allotList = await this.fetchAllotList()
    this.renderMap(allotList, false, nowLength)
    this.taskMapData = this.taskMapData.concat(allotList)
    
    
  }
  
  public async makePhoneCallClickHandler(event: Event, phone: string): Promise<string | undefined | void> {
    event.stopPropagation()
    if (!phone) {
      return Log.warn('Caused: makePhoneCallClickHandler parameter phone is empty', this.makePhoneCallClickHandler.name)
    }
    
    const params = {
      phone,
      taskType: TableNameEnum.Task
    }
    
    try {
      // 中通天鸿呼叫电话
      ctiCallOut(phone)
      // 之前的由后端呼叫电话
      const { code, message } = await dialout(params)
      if (code) {
        Platform.alert(message)
      }
      
    } catch (error) {
      Log.error(error, this.makePhoneCallClickHandler.name)
    }
  }
  
  public openBatchAllotDialog() {
    if(this.selectedTaskMapData.length < 1) {
      return Platform.alert(ALLOT_TASK_REQUIRED_MASSAGE)
    }
    
    // @ts-ignore
    this.BatchAllotDialogComponent?.openDialog(this.taskConfig)
  }
  
  public openPlanTimeDialog(event: Event, task: EsTask, index: number): void {
    event.stopPropagation()
    
    this.currentSelectedMarkTask = {
      data: task,
      index: index
    }
    // 设置当前选中的标记工单的计划时间字段数据
    this.setCurrentSelectedMarkTaskPlantimeField(task)
    
    this.$nextTick(() => {
      // @ts-ignore
      isCalendar ? this.CalendarPlanTimeDialogComponent.openDialog('modifyPlanTime') : this.PlanTimeDialogComponent.openDialog();
    })
  }
  
  public init(): void {
    this.$nextTick(async () => {
      this.hasNextPage = false
      this.taskMapData = []
      await this.fetchTaskTypesMap()
      this.initializeAllotList()
    })
  }
  
  public renderMap(list:any, refresh:boolean = true, nowIndex:number = 0) {
    this.markerList = []
    let marker: AMap.Marker | null
    
    list.forEach((task :any, index:number) => {
      marker = this.createMarker(task, index + nowIndex)
      if (marker) {
        // this.markerMap[task.id] = marker
        this.markerList.push(marker)
      }
    })
    this.$nextTick(()=>{
      if(!list.length && refresh)return this.$refs.baseMapContainer?.clearListMark()
      this.$refs.baseMapContainer?.setListMark(this.markerList, refresh)
    })
    
  }
  
  public setCurrentSelectedMarkTaskPlantimeField(task?: EsTask) {
    let taskType: TaskType | undefined = this.getTaskType(task)
    
    if (!taskType || !isObject(taskType) || !taskType.field || !isArray(taskType.field)) {
      return Log.warn('Caused taskType is empty or taskType.field not an Array', this.chooseSideListTaskClickHandler.name)
    }
    
    const fields: Field[] = taskType.field || []
    
    for (let field of fields) {
      if (isPlanTimeField(field)) {
        this.currentSelectedMarkTaskPlantimeField = field
        break
      }
    }
    
  }
  
  /**
   * @description 滚动侧边栏到选中的工单位置
   * @param {AllotMapDialogMarker} allotDialogMarker 标记点信息
   * @return {void}
   */  
  public scrollSideToSelectedTask(allotDialogMarker: AllotMapDialogMarker): void {
    const index: number = allotDialogMarker.index
    const element: HTMLElement = this.$refs[`side_item_${index}`] as HTMLElement
    element.scrollIntoView({ behavior: 'instant' })
  }
  
  /**
   * @description 切换是否显示地图侧边栏
   * @return {void}
   */  
  public toggleVisibleMapSide(): void {
    this.visibleMapSide = ! this.visibleMapSide
  }
  
  /**
   * @description 更改地图工单选中状态
   * @param {number} index 索引
   * @param {boolean} selected 选中状态
   * @return {void}
   */  
  public toggleMapTaskSelected(index: number, selected?: boolean): void {
    // 更改选中状态
    if (this.taskMapData[index]) {
      const task = this.taskMapData[index]
      const mapIndex = this.hasLatLngData.findIndex(t => t.id == task.id)

      const isSelected = isUndefined(selected) ? !task.selected : selected
      this.$set(this.taskMapData[index], 'selected', isSelected)

      // 重新创建标记
      this.$nextTick(() => {
        let div = document.createElement("div")
        div.innerHTML = this.buildTaskMapMarkerContent(task, index)
        this.$refs.baseMapContainer.changeMarkContent({markKey:task.id, content:this.buildTaskMapMarkerContent(task, index)})
      })
    }
  }
  
  /**
   * @description 更新计划时间操作
   * @param {string} newPlanTime 新计划时间值
   * @return {void}
   */  
  public updatePlanTime(newPlanTime: string): void {
    const currentSelectedMarkTaskIndex: number = this.currentSelectedMarkTask.index
    
    if (this.currentSelectedMarkTask.data) {
      this.currentSelectedMarkTask.data.planTime = newPlanTime
    }
    
    if (this.taskMapData[currentSelectedMarkTaskIndex]) {
      this.taskMapData[currentSelectedMarkTaskIndex].planTime = newPlanTime
    }

    
    this.$nextTick(() => {
      this.changeInfoWindowContent(this.currentSelectedMarkTask.data.id)
    })
    
    this.$message.success(i18n.t('common.base.tip.editSuccess') as string)
  }

  /**
   * @description 更新计划开始和结束时间操作
   * @param {string} newPlanTime 新计划时间值
   * @return {void}
   */  
  public updateCalendarPlanTime(newPlanTime: object): void {
    const currentSelectedMarkTaskIndex: number = this.currentSelectedMarkTask.index
    
    if (this.currentSelectedMarkTask.data) {
      // @ts-ignore
      if(this.currentSelectedMarkTask.data.planStartTimeShow) this.currentSelectedMarkTask.data.planStartTime = newPlanTime?.start;

      // @ts-ignore
      if(this.currentSelectedMarkTask.data.planEndTimeShow) this.currentSelectedMarkTask.data.planEndTime = newPlanTime?.end;
    }
    
    if (this.taskMapData[currentSelectedMarkTaskIndex]) {
      // @ts-ignore
      if(this.taskMapData[currentSelectedMarkTaskIndex].planStartTimeShow) this.taskMapData[currentSelectedMarkTaskIndex].planStartTime = newPlanTime?.start;

      // @ts-ignore
      if(this.taskMapData[currentSelectedMarkTaskIndex].planEndTimeShow) this.taskMapData[currentSelectedMarkTaskIndex].planEndTime = newPlanTime?.end;
    }
    
    // this.$nextTick(() => {
    //   const taskId = getTaskId(this.currentSelectedMarkTask.data)
    //   const marker: AMap.Marker = this.markerMap[taskId]
      
    //   this.openInfoWindow(marker)
    // })
    
    this.$message.success(i18n.t('common.base.tip.editSuccess') as string)
  }
  
}

export default AllotMapDialogMethods
